package com.gitee.wsl.eventbus

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.launch

sealed interface Action<T> {
    data class SendMessage<T>(val message: T) : Action<T>
}

data class State<T>(
    val messages: List<T> = emptyList()
)

interface Store<T> {
    fun send(action: Action<T>)
    val stateFlow: StateFlow<State<T>>
    val state get() = stateFlow.value
}

fun <T> CoroutineScope.sampleStore(block:(Store<T>.()->Unit)?= null): Store<T> {
    val mutableStateFlow = MutableStateFlow(State<T>())
    val channel: Channel<Action<T>> = Channel(Channel.UNLIMITED)
    val store = object : Store<T> {
        init {
            launch {
                channel.consumeAsFlow().collect { action ->
                    mutableStateFlow.value = chatReducer(mutableStateFlow.value, action)
                }
            }
        }

        override fun send(action: Action<T>) {
            launch {
                channel.send(action)
            }
        }

        override val stateFlow: StateFlow<State<T>> = mutableStateFlow
    }
    if (block != null) {
        block(store)
    }
    return store
}

internal fun <T> chatReducer(state: State<T>, action: Action<T>): State<T> =
    when (action) {
        is Action.SendMessage -> {
            state.copy(
                messages = (state.messages + action.message).takeLast(100)
            )
        }
    }
